
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Tilemaps;

public class PlacementProcess
{   
    private GameObject m_PlacementOutline; // 放置轮廓
    private BuildActionSO m_BuildAction;
    private Vector3Int[] m_HighlightPositions;
    private Tilemap m_WalkableTilemap;
    private Tilemap m_OverlayTilemap; 
    private Sprite m_PlaceholderTileSprite;
    private Tilemap[] m_UnreachableTilemaps;

    private Color m_HighlightColor = new Color(0, 0.8f, 1, 0.4f); // 高亮颜色
    private Color m_BlockedColor = new Color(1f, 0.2f, 0, 0.8f); // 阻塞颜色

    public PlacementProcess(
        BuildActionSO buildAction, 
        Tilemap walkableTilemap,
        Tilemap overlayTilemap,
        Tilemap[] unreachableTilemaps
    )
    {
        m_PlaceholderTileSprite = Resources.Load<Sprite>("Images/PlaceholderTileSprite");
        m_BuildAction = buildAction;
        m_WalkableTilemap = walkableTilemap;
        m_OverlayTilemap = overlayTilemap;
        m_UnreachableTilemaps = unreachableTilemaps;
    }

    public void Update()
    {
        if (m_PlacementOutline != null) // 如果有放置物体
        {
            HighlightTiles(m_PlacementOutline.transform.position);
        }

        if (HvoUtils.TryGetHoldPosition(out Vector3 worldPosition))
        {
            m_PlacementOutline.transform.position = SnapToGrid(worldPosition);
        }
    }

    public void ShowPlacementOutline() //点击建筑物，显示建筑物轮廓
    {
        // Debug.Log("ShowPlacementOutline");
        m_PlacementOutline = new GameObject("PlacementOutline");
        var render = m_PlacementOutline.AddComponent<SpriteRenderer>();
        render.sortingOrder = 999;
        render.color = new Color(1, 1, 1, 0.5f);
        render.sprite = m_BuildAction.PlacementSprite;
    }

    Vector3 SnapToGrid(Vector3 worldPosition) // 吸附到网格
    {
        return new Vector3(Mathf.FloorToInt(worldPosition.x), Mathf.FloorToInt(worldPosition.y), 0);
    }

    void HighlightTiles(Vector3 outlinePosition)  // 高亮平铺材质轮廓
    {
        Vector3Int buildingSize = m_BuildAction.BuildingSize; // 建筑物大小
        Vector3 pivotPosition = outlinePosition + m_BuildAction.OriginOffset;
        ClearHighlights(); // 清除之前的轮廓
        m_HighlightPositions = new Vector3Int[buildingSize.x * buildingSize.y]; // 用1维数组存储2维位置

        for (int x = 0; x < buildingSize.x; x++)
        {
            for (int y = 0; y < buildingSize.y; y++)
            {
                m_HighlightPositions[x + y * buildingSize.x] = new Vector3Int((int)pivotPosition.x + x, (int)pivotPosition.y + y, 0);
            }
        }

        foreach (var tilePosition in m_HighlightPositions)
        {
            var tile = ScriptableObject.CreateInstance<Tile>();
            tile.sprite = m_PlaceholderTileSprite;
            if (CanPlaceTile(tilePosition))
            {
                tile.color = m_HighlightColor;
            }
            else
            {
                tile.color = m_BlockedColor;
            }
            
            m_OverlayTilemap.SetTile(tilePosition, tile);
        }
    }

    void ClearHighlights()
    {
        if (m_HighlightPositions == null) return;

        foreach (var tilePosition in m_HighlightPositions)
        {
            m_OverlayTilemap.SetTile(tilePosition, null);
        }
    }

    bool CanPlaceTile(Vector3Int tilePosition)
    {
        return m_WalkableTilemap.HasTile(tilePosition) && 
        !IsInUnreachableTilemap(tilePosition) &&
        !IsBlockedByGameobject(tilePosition);
    }

    bool IsInUnreachableTilemap(Vector3Int tilePosition)
    {
        foreach (var tilemap in m_UnreachableTilemaps)
        {
            if (tilemap.HasTile(tilePosition)) return true;
        }

        return false;
    }

    bool IsBlockedByGameobject(Vector3Int tilePosition)
    {
        Vector3 tileSize = m_WalkableTilemap.cellSize; // 获取单位网格大小
        Collider2D[] colliders = Physics2D.OverlapBoxAll(tilePosition + tileSize / 2, tileSize*0.5f, 0); // 获取所有碰撞器,*0.5f是防止碰撞器边缘重叠

        foreach(var collider in colliders)
        {
            var layer = collider.gameObject.layer;
            if (layer == LayerMask.NameToLayer("Player"))
            {
                return true;
            }
        }

        return false;
    }

}